home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / imb9008.zip / PREPROC.BAS < prev    next >
BASIC Source File  |  1990-07-12  |  16KB  |  495 lines

  1. DECLARE FUNCTION PreAvail87% ()
  2. DECLARE SUB PreDefine (CV AS ANY, DefineTbl$, symbol$)
  3. DECLARE SUB PreElse (CV AS ANY)
  4. DECLARE SUB PreEndIf (CV AS ANY)
  5. DECLARE SUB PreErr (CV AS ANY, S$)
  6. DECLARE FUNCTION PreExist% (FileName$)
  7. DECLARE FUNCTION PreGetDosVer$ ()
  8. DECLARE FUNCTION PreGetEnvDefs$ (Tbl$, Parms AS ANY)
  9. DECLARE SUB PreGetSymbol (L$, C$, S$, O$)
  10. DECLARE SUB PreGetWord (L$, W$())
  11. DECLARE SUB PreIfDefined (CV AS ANY, DefineTbl$, Operand$)
  12. DECLARE SUB PreIfNDefined (CV AS ANY, DefineTbl$, Op$)
  13. DECLARE SUB PreInclude (Op$, DefineTbl$)
  14. DECLARE SUB PreProcessFile (FileIn$, DefineTbl$, IncStatus%)
  15. DECLARE SUB PreProcessLine (CV AS ANY, DefineTbl$)
  16. DECLARE SUB PreSetSysDefs (Tbl$, Parms AS ANY)
  17. DECLARE SUB PreUnDefine (CV AS ANY, DefineTbl$, symbol$)
  18. DECLARE FUNCTION PreValidFile% (FileIn$)
  19. DEFINT A-Z
  20.  
  21. 'BASIC 7.0 Users should change the next line to use
  22. 'the QBX.BI include file
  23.  
  24. '$INCLUDE: 'QB.BI'
  25.  
  26. 'Include the TABLMNGR.BI AND TABLMNGR.BAS files from the
  27. 'RAM Tables article
  28.  
  29. '$INCLUDE: 'TABLMNGR.BI'
  30.  
  31.     CLS
  32.  
  33. 'Initialize global variables and constants
  34.  
  35.     CONST True = -1, False = 0
  36.  
  37.     TYPE PreProcParameters              'Define the parameters
  38.         Sym     AS SymbolTableParameters  '  used for the
  39.         Chr     AS STRING * 2             '  preprocessor
  40.         EnvSym  AS STRING * 7
  41.     END TYPE
  42.  
  43.     TYPE CurrentLevelValues             'This structure maintains
  44.         FileName      AS STRING * 72      '  the values for the
  45.         FileInNbr     AS INTEGER          '  current level of IF/
  46.         LineNbr       AS INTEGER          '  FILE processing
  47.         PreStatus     AS INTEGER          'Output status before IF
  48.         CurrentStatus AS INTEGER          'Output status inside IF
  49.         IfFound       AS INTEGER          'These three variables
  50.         ElseFound     AS INTEGER          '  track the reading of
  51.         EndIfFound    AS INTEGER          '  these symbols
  52.     END TYPE
  53.  
  54.     DIM SHARED RegsX AS RegTypeX
  55.     DIM SHARED PreParms AS PreProcParameters
  56.  
  57.     PreParms.Sym.SWidth = 10      'Maximum symbol width
  58.     PreParms.Sym.Delim = "\"     'Delimiter between symbols in tbl
  59.     PreParms.Chr = "'%"          'Prefix to scan for in BASIC prog
  60.     PreParms.EnvSym = "PREPROC"  'Environment keyword
  61.  
  62. ' Initialize the symbol table
  63.  
  64.     IF NOT SymCreateTbl(DefineTbl$, PreParms.Sym, 1) THEN
  65.          PRINT "Error - Couldn't allocate symbol table"
  66.          END
  67.     END IF
  68.  
  69. ' Create automatic symbol definitions
  70.  
  71.     CALL PreSetSysDefs(DefineTbl$, PreParms)
  72.     InclPath$ = PreGetEnvDefs(DefineTbl$, PreParms)
  73.  
  74. ' Begin to process the file now
  75.  
  76.     FileCmd$ = COMMAND$
  77.     IF LEN(FileCmd$) <> 0 THEN
  78.         FileOut$ = FileCmd$ + ".PRE"
  79.         FileOutNbr = 1
  80.         OPEN FileOut$ FOR OUTPUT AS #FileOutNbr
  81.         CALL PreProcessFile(FileCmd$ + ".BAS", DefineTbl$, False)
  82.         CLOSE
  83.     ELSE
  84.         PRINT "No input file given on command line"
  85.     END IF
  86.     PRINT "Program terminated."
  87.     END
  88.  
  89. '----------------------------------------------------------------
  90.  
  91. '----------------------------------------------------------------
  92. '  Call an interrupt to check on
  93. '  math coprocessor availability
  94. '----------------------------------------------------------------
  95. FUNCTION PreAvail87
  96.     RegsX.ax = 0
  97.     CALL INTERRUPTX(&H11, RegsX, RegsX)
  98.     IF RegsX.ax AND 2 THEN
  99.         PreAvail87 = True
  100.     ELSE
  101.         PreAvail87 = False
  102.     END IF
  103. END FUNCTION
  104.  
  105. '----------------------------------------------------------------
  106. 'Define a symbol for the preprocessor by calling a TABLMNGR Func
  107. '----------------------------------------------------------------
  108. SUB PreDefine (CV AS CurrentLevelValues, DefineTbl$, symbol$)
  109.     IF NOT SymDefine(DefineTbl$, symbol$, PreParms.Sym) THEN
  110.         PRINT CV.FileName; CV.LineNbr;
  111.         PRINT "Warning - " + symbol$ + " duplicate definition"
  112.         PRINT "or symbol contains the table delimiter character ";
  113.         PRINT PreParms.Sym.Delim
  114.     END IF
  115. END SUB
  116.  
  117. '----------------------------------------------------------------
  118. 'Manage the preprocessor ELSE tasks
  119. '  PreElse checks for duplicate ELSE's and ELSE's without IF's
  120. '----------------------------------------------------------------
  121. SUB PreElse (CV AS CurrentLevelValues)
  122.     IF CV.IfFound THEN
  123.         IF CV.ElseFound THEN
  124.             CALL PreErr(CV, "Duplicate Else Found")
  125.         ELSE
  126.             ElseFound = True
  127.             IF CV.PreStatus THEN
  128.                 CV.CurrentStatus = NOT CV.CurrentStatus 'Swap ELSE status
  129.             ELSE
  130.                 CV.CurrentStatus = False 'Must be outputting outside IF
  131.             END IF                     '  for us to start ouputting now
  132.         END IF
  133.     ELSE
  134.         CALL PreErr(CV, "ELSE found without an IF statement")
  135.     END IF
  136. END SUB
  137.  
  138. '----------------------------------------------------------------
  139. 'Manage the preprocessor ENDIF tasks
  140. '----------------------------------------------------------------
  141. SUB PreEndIf (CV AS CurrentLevelValues)
  142.     IF CV.IfFound THEN
  143.         CV.EndIfFound = True
  144.         IfFound = False     'Set this so you end the current IF level
  145.     ELSE
  146.         PreErr CV, "ENDIF without IF found"
  147.     END IF
  148. END SUB
  149.  
  150. '----------------------------------------------------------------
  151. 'Print error messages to screen
  152. '----------------------------------------------------------------
  153. SUB PreErr (CV AS CurrentLevelValues, S$)
  154.     PRINT "+ "; RTRIM$(CV.FileName); " Line #: "; CV.LineNbr;
  155.     PRINT "Preprocessor ERROR-"; S$
  156. END SUB
  157.  
  158. '----------------------------------------------------------------
  159. ' See if a given file exists using
  160. ' DOS "Search for first match" service &H4E
  161. '----------------------------------------------------------------
  162. FUNCTION PreExist% (FileName$)
  163.  
  164.     RegsX.ax = &H4E00
  165.     RegsX.cx = 63  ' Search for all files
  166.  
  167.     Spec$ = FileName$ + CHR$(0)
  168.  
  169. 'BASIC 7.0 Users should change all occurences of
  170. 'VARSEG to SSEG (there's only one VARSEG in this program)
  171.  
  172.     RegsX.ds = VARSEG(Spec$) ' Load DS:DX with
  173.     RegsX.dx = SADD(Spec$) ' address of Spec$
  174.  
  175.     CALL INTERRUPTX(&H21, RegsX, RegsX) ' CALL DOS
  176.  
  177. ' If AX contains a value, then file does not exist
  178.  
  179.     SELECT CASE RegsX.ax
  180.         CASE 0
  181.             PreExist% = True
  182.         CASE ELSE
  183.             PreExist% = False
  184.     END SELECT
  185.  
  186. END FUNCTION
  187.  
  188. '----------------------------------------------------------------
  189. 'Calls interrupt &H21, function &H30 to create a symbol for the
  190. '  current DOS version
  191. '----------------------------------------------------------------
  192. FUNCTION PreGetDosVer$
  193.     RegsX.ax = &H3000
  194.     CALL INTERRUPTX(&H21, RegsX, RegsX)
  195.     MajorVersion = RegsX.ax MOD 256
  196.     MinorVersion = RegsX.ax \ 256
  197.     DosV$ = "DOS" + RIGHT$(STR$(MajorVersion), 1)
  198.     PreGetDosVer$ = DosV$ + RIGHT$(STR$(MinorVersion), 2)
  199. END FUNCTION
  200.  
  201. '----------------------------------------------------------------
  202. 'Retrieve the symbols you define as part of your environment
  203. '  using the value you store Parms.EnvSym.  Also retrieves the
  204. '  INCLUDE environment variable if it exists.
  205. '----------------------------------------------------------------
  206. FUNCTION PreGetEnvDefs$ (Tbl$, Parms AS PreProcParameters)
  207.  
  208.     LenEnvSym = LEN(Parms.EnvSym)
  209.     EnvLine = 1
  210.     IPath$ = ""                 'Initialize the include paths value
  211.  
  212.     DO     'Loop until find both values looking for or end of table
  213.  
  214.         Env$ = ENVIRON$(EnvLine)
  215.  
  216.         IF LEFT$(Env$, LenEnvSym) = Parms.EnvSym THEN
  217.  
  218.             BegDefPos = INSTR(Env$, "=") + 1
  219.  
  220.             DO UNTIL BegDefPos > LEN(Env$)
  221.                 EndDefPos = INSTR(BegDefPos, Env$, ";")
  222.                 IF EndDefPos = 0 THEN EndDefPos = LEN(Env$) + 1
  223.                 EnvSym$ = MID$(Env$, BegDefPos, EndDefPos - BegDefPos)
  224.                 IF NOT SymDefine(Tbl$, EnvSym$, Parms.Sym) THEN
  225.                     PRINT "Unable to define "; EnvSym$; " from environment"
  226.                 END IF
  227.                 BegDefPos = EndDefPos + 1
  228.             LOOP
  229.  
  230.             FoundPP = True                 'Sets one of the found flags
  231.  
  232.         ELSEIF LEFT$(Env$, 7) = "INCLUDE" THEN
  233.  
  234.             IPath$ = MID$(Env$, 9)
  235.             FoundInclude = True            'Sets one of the found flags
  236.  
  237.         END IF
  238.  
  239.         IF FoundPP AND FoundInclude THEN EXIT DO
  240.         EnvLine = EnvLine + 1
  241.         Env$ = ENVIRON$(EnvLine)
  242.  
  243.     LOOP WHILE LEN(Env$)
  244.  
  245.     PreGetEnvDefs$ = IPath$
  246.  
  247. END FUNCTION
  248.  
  249. '----------------------------------------------------------------
  250. 'Gets the first two symbols from the input line
  251. '  Checks to see if the first one matches the preprocessor prefix
  252. '  symbols.  If it matches, set symbol and operand values
  253. '----------------------------------------------------------------
  254. SUB PreGetSymbol (L$, C$, S$, O$)
  255.  
  256.     DIM Word$(2)
  257.     L$ = UCASE$(LTRIM$(RTRIM$(L$)))
  258.     C$ = "IGNORE"    'Ignore non-commands
  259.     S$ = ""
  260.     O$ = ""
  261.     IF LEN(L$) <> 0 THEN
  262.         PreGetWord (L$), Word$()
  263.         Prefix$ = LEFT$(Word$(1), 2)
  264.         IF Prefix$ = PreParms.Chr OR Prefix$ = "'$" THEN
  265.             C$ = "PreProc"
  266.             S$ = MID$(Word$(1), 3)
  267.             O$ = Word$(2)
  268.         END IF
  269.     END IF
  270. END SUB
  271.  
  272. '----------------------------------------------------------------
  273. 'Loop through a line to retrieve the individual words delimited
  274. '  by spaces.
  275. '----------------------------------------------------------------
  276. SUB PreGetWord (L$, W$())
  277.     Delim$ = " "
  278.     BegPos = 1
  279.     LenL = LEN(L$)
  280.     FOR I% = 1 TO 2                         'Get only first 2 words
  281.         DelimPos = INSTR(BegPos, L$, Delim$)
  282.         IF DelimPos = 0 THEN DelimPos = LenL + 1
  283.         W$(I%) = MID$(L$, BegPos, DelimPos - BegPos)
  284.         BegPos = DelimPos + 1
  285.         IF BegPos > LenL THEN EXIT FOR
  286.     NEXT I%
  287. END SUB
  288.  
  289. '----------------------------------------------------------------
  290. 'Manage tasks for Preprocessing IfDefined command.
  291. '----------------------------------------------------------------
  292. SUB PreIfDefined (CV AS CurrentLevelValues, DefineTbl$, Operand$)
  293.  
  294.     DIM NewCV AS CurrentLevelValues    'Create a new copy of record
  295.                                                                          '  To manage a new IF level
  296.     NewCV.FileName = CV.FileName
  297.     NewCV.FileInNbr = CV.FileInNbr
  298.     NewCV.LineNbr = CV.LineNbr
  299.     NewCV.PreStatus = CV.CurrentStatus
  300.     NewCV.IfFound = True
  301.     NewCV.ElseFound = False
  302.     NewCV.EndIfFound = False
  303.  
  304. 'Set output status to true if currently outputting and condition
  305. '  is true, otherwise set current output status to false
  306.  
  307.     IF CV.CurrentStatus THEN
  308.         IF SymDefined(DefineTbl$, Operand$, PreParms.Sym) THEN
  309.             NewCV.CurrentStatus = True
  310.         ELSE
  311.             NewCV.CurrentStatus = False
  312.         END IF
  313.     ELSE
  314.         NewCV.CurrentStatus = False
  315.     END IF
  316.  
  317. 'Recursively call a new copy of the PreProcessLine routine
  318.  
  319.     DO WHILE NOT EOF(NewCV.FileInNbr) AND (NOT NewCV.EndIfFound)
  320.         CALL PreProcessLine(NewCV, DefineTbl$)
  321.     LOOP
  322.     CV.LineNbr = NewCV.LineNbr
  323. END SUB
  324.  
  325. '----------------------------------------------------------------
  326. 'Manage tasks for Preprocessing IfNDefined command.
  327. '----------------------------------------------------------------
  328. SUB PreIfNDefined (CV AS CurrentLevelValues, DefineTbl$, Op$)
  329.  
  330.     DIM NewCV AS CurrentLevelValues    'Create a new copy of record
  331.                                                                          '  to manage a new IF level
  332.     NewCV.FileName = CV.FileName
  333.     NewCV.FileInNbr = CV.FileInNbr
  334.     NewCV.LineNbr = CV.LineNbr
  335.     NewCV.PreStatus = CV.CurrentStatus
  336.     NewCV.IfFound = True
  337.     NewCV.ElseFound = False
  338.     NewCV.EndIfFound = False
  339.  
  340. 'Set output status to true if currently outputting and condition
  341. '  is true, otherwise set current output status to false
  342.  
  343.     IF CV.CurrentStatus THEN
  344.         IF (NOT SymDefined(DefineTbl$, Op$, PreParms.Sym)) THEN
  345.             NewCV.CurrentStatus = True
  346.         ELSE
  347.             NewCV.CurrentStatus = False
  348.         END IF
  349.     ELSE
  350.         NewCV.CurrentStatus = False
  351.     END IF
  352.  
  353.     DO WHILE NOT EOF(NewCV.FileInNbr) AND (NOT NewCV.EndIfFound)
  354.         CALL PreProcessLine(NewCV, DefineTbl$)
  355.     LOOP
  356.     CV.LineNbr = NewCV.LineNbr
  357.  
  358. END SUB
  359.  
  360. '----------------------------------------------------------------
  361. 'Manage tasks for Preprocessing Include command
  362. '  Add lines from Include file into output file so include files
  363. '  can have preprocessing lines also
  364. '----------------------------------------------------------------
  365. SUB PreInclude (Op$, DefineTbl$)
  366.     Op$ = MID$(Op$, 2, LEN(Op$) - 2)
  367.     CALL PreProcessFile(Op$, DefineTbl$, True) 'New copy of routine
  368. END SUB
  369.  
  370. '----------------------------------------------------------------
  371. 'Manage tasks for Preprocessing File command.
  372. '----------------------------------------------------------------
  373. SUB PreProcessFile (FileIn$, DefineTbl$, IncStatus)
  374.     DIM CV AS CurrentLevelValues 'Create a new record for new level
  375.     SELECT CASE PreValidFile(FileIn$)        'Make sure file exists
  376.         CASE 0
  377.             CV.FileName = FileIn$
  378.             CV.FileInNbr = FREEFILE              'Get new valid number
  379.             CV.LineNbr = 0
  380.             CV.CurrentStatus = True
  381.             CV.PreStatus = True
  382.             CV.IfFound = False
  383.             CV.ElseFound = False
  384.             CV.EndIfFound = False
  385.             OPEN CV.FileName FOR INPUT AS #CV.FileInNbr
  386.             DO WHILE NOT EOF(CV.FileInNbr)
  387.                 PreProcessLine CV, DefineTbl$      'Invoke new copy
  388.             LOOP
  389.             CLOSE CV.FileInNbr
  390.         CASE 1
  391.             PRINT "Can't find file->"; FileIn$ 'If can't file including
  392.             IF IncStatus THEN                  '  keep line in file
  393.                 PRINT #1, "'$INCLUDE: '" + FileIn$ + "'"
  394.             END IF
  395.         CASE 2
  396.             PRINT CV.FileName;
  397.             PRINT "<-Invalid format - may be BASIC fast save format"
  398.     END SELECT
  399. END SUB
  400.  
  401. '----------------------------------------------------------------
  402. 'Manage tasks for Preprocessing Line command.
  403. '----------------------------------------------------------------
  404. SUB PreProcessLine (CV AS CurrentLevelValues, DefineTbl$)
  405.     LINE INPUT #CV.FileInNbr, LineIn$
  406.  
  407.     DO
  408.         CV.LineNbr = CV.LineNbr + 1
  409.         CALL PreGetSymbol((LineIn$), Class$, symbol$, Op$)
  410.         IF Class$ <> "PreProc" THEN
  411.             IF CV.CurrentStatus THEN
  412.                 PRINT #1, LineIn$
  413.             END IF
  414.         ELSE
  415.             SELECT CASE symbol$   'Split CASE into cmds that require
  416.                 CASE "ELSE"         '  operands and those who don't
  417.                     CALL PreElse(CV)
  418.                 CASE "ENDIF"
  419.                     CALL PreEndIf(CV)
  420.                     IF CV.EndIfFound THEN EXIT SUB
  421.                 CASE ELSE                'These commands require operands
  422.                     IF Op$ <> "" THEN
  423.                         SELECT CASE symbol$
  424.                             CASE "DEFINE"
  425.                                 IF CV.CurrentStatus THEN
  426.                                     CALL PreDefine(CV, DefineTbl$, Op$)
  427.                                 END IF
  428.                             CASE "UNDEFINE"
  429.                                 IF CV.CurrentStatus THEN
  430.                                     CALL PreUnDefine(CV, DefineTbl$, Op$)
  431.                                 END IF
  432.                             CASE "IFDEFINED"
  433.                                 CALL PreIfDefined(CV, DefineTbl$, Op$)
  434.                             CASE "IFNDEFINED"
  435.                                 CALL PreIfNDefined(CV, DefineTbl$, Op$)
  436.                             CASE "INCLUDE:"
  437.                                 IF CV.CurrentStatus THEN
  438.                                     CALL PreInclude(Op$, DefineTbl$)
  439.                                 END IF
  440.                             CASE ELSE
  441.                                 PRINT #1, "'Invalid Preprocessing command: ";
  442.                                 PRINT #1, LineIn$
  443.                         END SELECT
  444.                     ELSE
  445.                         PRINT #1, "'Missing operand for "; symbol$;
  446.                         PRINT #1, " preprocessing command"
  447.                     END IF
  448.             END SELECT
  449.         END IF
  450.         IF NOT (EOF(CV.FileInNbr)) THEN
  451.             LINE INPUT #CV.FileInNbr, LineIn$
  452.         END IF
  453.     LOOP UNTIL EOF(CV.FileInNbr)
  454. END SUB
  455.  
  456. '----------------------------------------------------------------
  457. 'Set the automatic system symbols
  458. '----------------------------------------------------------------
  459. SUB PreSetSysDefs (Tbl$, Parms AS PreProcParameters)
  460.     IF PreAvail87 THEN   'Add Coprocessor to table if available
  461.         Dummy = SymDefine(Tbl$, "AVAIL87", Parms.Sym)
  462.     END IF
  463.     Dummy = SymDefine(Tbl$, PreGetDosVer$, Parms.Sym)
  464. END SUB
  465.  
  466. '----------------------------------------------------------------
  467. 'Manage tasks for Preprocessing UnDefine command.
  468. '----------------------------------------------------------------
  469. SUB PreUnDefine (CV AS CurrentLevelValues, DefineTbl$, symbol$)
  470.     IF NOT SymUnDefine(DefineTbl$, symbol$, PreParms.Sym) THEN
  471.         PRINT CV.FileName; CV.LineNbr;
  472.         PRINT "Warning - " + symbol$ + " tried to undefine"
  473.         PRINT "non-existent symbol or symbol contains the table"
  474.         PRINT "delimiter character "; PreParms.Sym.Delim
  475.     END IF
  476. END SUB
  477.  
  478. '----------------------------------------------------------------
  479. 'Make sure the file exists and check first byte to see if TXT fmt
  480. '  which seems to be &HFC for BASIC quick save format
  481. '----------------------------------------------------------------
  482. FUNCTION PreValidFile (FileIn$)
  483.     PreValidFile = 0
  484.     IF NOT PreExist(FileIn$) THEN
  485.         PreValidFile = 1
  486.     ELSE
  487.         TestNbr = FREEFILE
  488.         OPEN FileIn$ FOR BINARY AS TestNbr
  489.         TestByte$ = " ": GET TestNbr, 1, TestByte$
  490.         CLOSE TestNbr
  491.         IF TestByte$ = CHR$(&HFC) THEN PreValidFile = 2
  492.     END IF
  493. END FUNCTION
  494.  
  495.